iT邦幫忙

2023 iThome 鐵人賽

DAY 6
1
自我挑戰組

複習 JavaScript 核心概念系列 第 6

[Day 06] 記憶體管理

  • 分享至 

  • xImage
  •  

JavaScript 有自己的記憶體回收機制,會透過一個稱作 垃圾回收器(garbage collector) 的系統,追蹤和釋放一些不再使用的記憶體空間。然而這並不代表我們可以完全不管記憶體的使用狀況,在程式碼撰寫不當的情況下仍可能導致 記憶體洩漏(Memory Leak)的情形發生。今天就來談談 JavaScript 的記憶體管理機制吧。


記憶體生命週期

這邊直接引用 MDN 的描述:

不論是哪種程式語言,記憶體生命週期(運作方式)幾乎總是一樣:

  1. 配置你程式需要的記憶體空間
  2. 使用配置到的記憶體空間(讀,寫)
  3. 當不再使用時釋放已被配置的記憶體空間

在所有語言中,第二點的(運作方式)是確定的。第一點以及最後一點在低階語言中是確定的,但是在高階語言如 JavaScript 則通常是不明確的。


JavaScript 的記憶體配置

JavaScript 的記憶體管理是基於 Stack(堆疊)Heap(堆積) 的概念。
Stack通常用於儲存基本變數和函式調用,而Heap通常用於儲存複雜資料結構(如物件和函式)。

  • Stack(堆疊):這是一種用於儲存靜態資料的資料結構。靜態資料是指在程式編譯時引擎已知其大小的資料,例如 JavaScript 中的 stringnumberbooleannullundefined。還包括指向物件和函數的引用。靜態資料使用了固定的記憶體空間。

  • Heap(堆積) :用於儲存 JavaScript 中的物件函式等。系統不會分配固定的記憶體空間,而是根據需要動態分配空間大小。

這裡借用 geeksforgeeks 的範例圖來幫助理解:


JavaScript 的記憶體回收機制

JavaScript 會透過 垃圾回收器(garbage collector) 來檢查和釋放不再使用的記憶體空間,一樣來看 MDN 對其的描述:

高階的語言 (e.g. JavaScript) 有一個叫作垃圾回收器(garbage collector) 的系統,他的工作是追蹤記憶體分配的使用情況,以便自動釋放一些不再使用的記憶體空間。但這個垃圾回收器只是「儘量」做到自動釋放記憶體空間,因為判斷記憶體空間是否要繼續使用,這件事是「不可判定(undecidable)」的(不能用演算法來解決)。

這裡就不詳述關於回收機制的演算法了。
簡單來說,JavaScript 大部分情況下是能自動釋放記憶體的,但它也沒有厲害到能百分百找到「不再被使用的記憶體空間」,可能導致這是我們在開發時要特別注意的地方。

記憶體洩漏(Memory Leak)

記憶體洩漏(Memory Leak) 是指在程式執行期間,已經不再需要的記憶體區域(例如變數、物件、陣列等)未被正確釋放或回收,導致這些記憶體區域一直占用系統資源,最終可能導致程式性能下降,甚至因記憶體不足導致系統崩潰。


一些不再使用的記憶體未被釋放的例子

全域變數

全域變數在整個程式的生命週期中都存在,只有當程式運行結束時才會被釋放。這意味著如果你不再需要某個全域變數,但忘記解除對它的引用,它將一直存在於記憶體中,這可能導致記憶體洩漏。

let x = [1, 2, 3]; // x 是全域變數,故即使之後不再使用,它仍占用記憶體空間
console.log(x);

if (true) {
  let y = [4, 5, 6]; // y 是區域變數,故回收機制會在適當時機釋放記憶體空間
  console.log(y);
}

閉包

閉包(closure)也可能導致記憶體洩漏。閉包會在之後的章節談到,所以這裡可以先看看就好。

這邊先簡單知道,閉包使內部函式能夠訪問外部函式的作用域。函式作用域的變數在函式執行完畢後會被清理,但閉包會在其執行後保持對外部作用域變數的引用,使得這些外部作用域變數即使不再使用卻不會被清除,進而導致記憶體洩漏的問題。

以下是一個例子,其中 largeArray 雖然不是全域變數,
但由於閉包的特性,導致函式執行完畢後 largeArray 未被清除。

function outer() {
  let largeArray = []; 

  return function (num) {
    largeArray.push(num);
  }
}

const fn = outer();

for (let i = 0; i < 10000000; i++) {
  fn(i);
}

結語

今天介紹了 JavaScript 的記憶體管理,談到了 Stack(堆疊)Heap(堆積),並簡單說明 垃圾回收器(garbage collector) 的回收機制,以及最重要的是要避免 記憶體洩漏(Memory Leak)的發生。

參考資料:


上一篇
[Day 05] 提升(Hoisting)
下一篇
[Day 07] 執行環境、執行堆疊
系列文
複習 JavaScript 核心概念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言